package com.czh.gateway.exception;

import cn.dev33.satoken.exception.DisableServiceException;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import com.czh.gateway.constants.ResourcesConstant;
import com.czh.gateway.entity.ResponseResult;
import com.czh.gateway.enums.ResponseResultEnum;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import reactor.util.annotation.NonNull;

import java.util.Objects;

/**
 * 网关层的全局异常处理
 * @author caozaihui
 * @version 1.0
 * @since 2024/8/21 下午 11:44
 */
@Slf4j
@Component
public class GlobalException implements ErrorWebExceptionHandler {
    @NonNull
    @Override
    public Mono<Void> handle(ServerWebExchange exchange,@NonNull Throwable ex) {
        ServerHttpResponse response = exchange.getResponse();
        ObjectMapper objectMapper = new ObjectMapper();
        ResponseResult result;
        ex = ex.getCause();
        if (ex instanceof NotLoginException){
            result = ResponseResult.error(ResponseResultEnum.NOT_LOGIN);
        } else if (ex instanceof NotPermissionException || ex instanceof NotRoleException) {
            result = ResponseResult.error(ResponseResultEnum.PERMISSION_DENIED);
        } else if (ex instanceof DisableServiceException e){
            result = ResponseResult.error(ResponseResultEnum.DISABLED_ACCOUNT);
            result.setCode(ResponseResultEnum.DISABLED_ACCOUNT.getCode());
            result.setMessage("当前账号 " + e.getService() + " 服务已被封禁 (level=" + e.getLevel() + ")：" + e.getDisableTime() + "秒后解封");
        }  else {
            result = ResponseResult.error(ResponseResultEnum.SERVER_ERROR);
        }
        if (Objects.nonNull(ex)){
            log.error("网关异常",ex);
        }
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        return response.writeWith(Mono.fromSupplier(()->{
            DataBufferFactory dataBufferFactory = response.bufferFactory();
            byte [] bytes;
            try {
                bytes =  objectMapper.writeValueAsBytes(result);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
            return  dataBufferFactory.wrap(bytes);
        }));
    }
}
